package com.mobile.util.config.aop;
import com.mobile.util.JwtUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

@Aspect
@Component
public class AutoFillAspect {

    // 切入点：拦截所有标记了 @AutoFill 的方法
    @Pointcut("@annotation(autoFill)")
    public void pointCut(AutoFill autoFill) {}

    // 前置通知：在方法执行前填充字段
    @Before("pointCut(autoFill)")
    public void before(JoinPoint joinPoint, AutoFill autoFill) {

        // 1. 获取当前登录用户（从 Shiro 的 Subject 中获取，也可从 ThreadLocal 中获取）
        String loginUser = this.getUserCode();
        if (loginUser == null) {
            throw new RuntimeException("未获取到登录用户信息");
        }

        // 2. 获取方法参数（假设 DTO 是方法的第一个参数）
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;  // 无参数，无需处理
        }
        Object dto = args[0];  // 假设 DTO 是方法的第一个参数

        // 3. 根据操作类型填充字段（需确保 DTO 有对应的 setter 方法）
        try {
            if (autoFill.value() == OperateType.INSERT) {
                // 新增：填充 createUser、createDatetime
                dto.getClass().getMethod("setCreateUser", String.class).invoke(dto, loginUser);
                dto.getClass().getMethod("setUpdateUser", String.class).invoke(dto, loginUser);
            } else if (autoFill.value() == OperateType.UPDATE) {
                // 修改：填充 updateUser、updateDatetime
                dto.getClass().getMethod("setUpdateUser", String.class).invoke(dto, loginUser);
            }
        } catch (Exception e) {
            throw new RuntimeException("自动填充操作人信息失败：" + e.getMessage());
        }
    }

    @Around("pointCut(autoFill)")
    public Object around(ProceedingJoinPoint joinPoint, AutoFill autoFill) throws Throwable {
        System.out.println("拦截到方法：" + joinPoint.getSignature().getName()); // 打印方法名
        try {
            // 填充逻辑
            return joinPoint.proceed();
        } catch (Exception e) {
            System.err.println("自动填充失败：" + e.getMessage()); // 打印异常
            throw e;
        }
    }
    public String getUserCode() {
        String token = this.getRequest().getHeader("Access-Token");
        if (Optional.ofNullable(token).isPresent()) {
            return JwtUtil.getClaim(token, JwtUtil.ACCOUNT);
        }
        return null;
    }
    /**得到request对象
     * @return
     */
    public HttpServletRequest getRequest() {
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        return request;
    }
}


